<template>
  <div class="analysis-filter-group">
    <!--头部-->
    <div class="group-header" :style="headerStyle" @click="onCollapseChange">
      <a-icon class="collapsible-icon" :type="collapse ? 'down' : 'right'" />
      <div v-if="!isEditting" class="group-name">{{ filterGroupName }}</div>
      <!--重命名输入框-->
      <div v-else>
        <a-input
          v-model="filterGroupName"
          v-focus
          class="rename-input"
          @keyup.enter.native="$event.target.blur"
          @blur="onRename"
          @click="onEditting"
        />
      </div>

      <!--击进行重命名-->
      <a-tooltip>
        <template slot="title">重命名</template>
        <a-icon-font
          v-if="!isEditting"
          class="tab-name-edit-icon"
          type="iconicon-beifen6"
          @click="onEditting"
        />
      </a-tooltip>
      <a-button
        size="small"
        class="run-button"
        :disabled="!runable"
        @click="runFilter"
        >运行
      </a-button>

      <!--删除过滤组-->
      <a-tooltip v-if="deletable">
        <template slot="title">删除</template>
        <a-icon-font
          class="delete-button"
          type="iconicon-beifen5"
          @click="deleteFilterGroup"
        />
      </a-tooltip>
    </div>

    <!--内容-->
    <div v-if="collapse" class="group-body">
      <!--所有过滤器-->
      <div
        v-for="(filter, index) in filters"
        :key="filter.filter.id"
        class="filter-item"
        :style="itemStyle(filter.filter.id)"
        @click="onSelectRow(filter.filter)"
      >
        <!--用一个宽度占位，表示层级-->
        <div :style="{ width: `${filter.layer * 12}px` }" />
        <div
          v-show="filters.length > 1"
          :style="{
            left: `${21 + filter.layer * 12}px`,
            height: `${verticalLineHeight(filter.layer, index)}px`,
          }"
          class="short-vertical-line"
        />
        <div v-show="filters.length > 1" class="circle" />
        <div v-show="filters.length > 1" class="short-horizontal-line" />

        <!--过滤器选择-->
        <a-dropdown :trigger="['click']" class="dropdown">
          <a
            :class="`ant-dropdown-link ${
              filter.filter.id > 0 && !invalidFilters.includes(filter.filter.id)
                ? 'selected-filter'
                : 'hint-msg'
            }`"
            @click="
              (e) => {
                e.preventDefault()
                loadAttributes(filter.filter.parentId)
              }
            "
          >
            {{ filter.filter.name }}

            <!--属性不存在-->
            <a-tooltip v-if="invalidFilters.includes(filter.filter.id)">
              <template slot="title">过滤器失效</template>
              <a-icon-font style="opacity: 1;" type="iconweiwanpeizhi" />
            </a-tooltip>
          </a>
          <a-menu
            v-if="filter.filter.id < 0"
            slot="overlay"
            @click="(e) => addFilter(e, filter.filter.parentId, index)"
          >
            <a-menu-item key="节点类型">节点</a-menu-item>
            <a-sub-menu key="边" title="边">
              <a-menu-item key="边的类型">边类型</a-menu-item>
              <a-menu-item key="边的权重范围">权重范围</a-menu-item>
              <a-sub-menu key="仅保留" title="仅保留">
                <a-menu-item key="仅保留有向边">有向边</a-menu-item>
                <a-menu-item key="仅保留无向边">无向边</a-menu-item>
                <a-menu-item key="仅保留双向边">双向边</a-menu-item>
              </a-sub-menu>
              <a-menu-item key="移除自环边">移除自环边</a-menu-item>
            </a-sub-menu>
            <a-sub-menu key="属性" title="属性">
              <a-sub-menu
                v-for="attr in aviailableAttributes"
                :key="attr.key"
                :title="attr.key"
              >
                <a-menu-item v-for="value in attr.value" :key="value.key">
                  {{ value.value }}
                </a-menu-item>
              </a-sub-menu>
            </a-sub-menu>
            <a-sub-menu key="拓扑" title="拓扑">
              <a-menu-item key="K-核心">K-核心</a-menu-item>
              <a-menu-item key="具有自环">具有自环</a-menu-item>
              <a-sub-menu key="范围" title="范围">
                <a-menu-item key="度范围">度范围</a-menu-item>
                <a-menu-item key="入度范围">入度范围</a-menu-item>
                <a-menu-item key="出度范围">出度范围</a-menu-item>
              </a-sub-menu>
            </a-sub-menu>
            <a-sub-menu key="操作" title="操作">
              <a-menu-item key="非">非</a-menu-item>
              <a-menu-item key="交集">交集</a-menu-item>
              <a-menu-item key="并集">并集</a-menu-item>
            </a-sub-menu>
          </a-menu>
          <a-menu
            v-else
            slot="overlay"
            @click="(e) => updateFilter(e, filter.layer, index)"
          >
            <a-menu-item key="节点类型">节点</a-menu-item>
            <a-sub-menu key="边" title="边">
              <a-menu-item key="边的类型">边类型</a-menu-item>
              <a-menu-item key="边的权重范围">权重范围</a-menu-item>
              <a-sub-menu key="仅保留" title="仅保留">
                <a-menu-item key="仅保留有向边">有向边</a-menu-item>
                <a-menu-item key="仅保留无向边">无向边</a-menu-item>
                <a-menu-item key="仅保留双向边">双向边</a-menu-item>
              </a-sub-menu>
              <a-menu-item key="移除自环边">移除自环边</a-menu-item>
            </a-sub-menu>
            <a-sub-menu key="属性" title="属性">
              <a-sub-menu
                v-for="attr in aviailableAttributes"
                :key="attr.key"
                :title="attr.key"
              >
                <a-menu-item v-for="value in attr.value" :key="value.key">
                  {{ value.value }}
                </a-menu-item>
              </a-sub-menu>
            </a-sub-menu>
            <a-sub-menu key="拓扑" title="拓扑">
              <a-menu-item key="K-核心">K-核心</a-menu-item>
              <a-menu-item key="具有自环">具有自环</a-menu-item>
              <a-sub-menu key="范围" title="范围">
                <a-menu-item key="度范围">度范围</a-menu-item>
                <a-menu-item key="入度范围">入度范围</a-menu-item>
                <a-menu-item key="出度范围">出度范围</a-menu-item>
              </a-sub-menu>
            </a-sub-menu>
            <a-sub-menu key="操作" title="操作">
              <a-menu-item key="非">非</a-menu-item>
              <a-menu-item key="交集">交集</a-menu-item>
              <a-menu-item key="并集">并集</a-menu-item>
            </a-sub-menu>
          </a-menu>
        </a-dropdown>

        <div class="op-group">
          <!--删除，不可用状态-->
          <a-icon-font
            v-if="filters.length <= 1 && filters[0].filter.id < 0"
            class="del-noallowed"
            type="iconjianshao"
          />

          <!--删除-->
          <a-tooltip v-else>
            <template slot="title">删除此条</template>
            <a-icon-font
              type="iconjianshao"
              @click="(event) => deleteFilter(event, index)"
            />
          </a-tooltip>

          <!--添加-->
          <a-tooltip placement="topRight">
            <template slot="title"
              >{{ addIconHint(filter.filter.subType) }}
            </template>
            <a-icon-font
              type="iconzengjia"
              @click="
                (event) =>
                  addCandidateFilter(event, filter.filter.id, filter.layer + 1)
              "
            />
          </a-tooltip>
        </div>
      </div>
    </div>

    <!--分割线-->
    <div class="divider" />
  </div>
</template>

<script lang="ts">
import { Component, Emit, Prop, Vue, Watch } from 'vue-property-decorator'
import {
  Filter,
  filterMapType,
  FilterPipeline,
} from '@/components/graph-analysis/right-drawer/data-filter/data-filter'
import GraphAnalysis from '@/store/modules/graphanalysis'
// import {debounce} from 'lodash'

@Component({
  components: {},
  directives: {
    focus: {
      inserted: (element: any) => {
        element.focus()
      },
    },
  },
})
export default class FilterGroup extends Vue {
  @Prop() private filterGroup!: FilterPipeline
  @Prop() private groups!: []

  private filterGroupName: string = '' // 过滤组名字
  private collapse: boolean = true // 是否展开
  private isEditting: boolean = false // 是否正在过滤组改名状态

  // 所有已选择过滤器，数据结构为{filter:Filter,layer:number}
  // 其中filter是过滤器，如果filter的id为负数，则表示是未选择过滤条件的过滤器
  // layer是过滤器所在层级，由深度优先搜索决定
  private filters: any[] = []

  // 当前可用的属性操作
  private aviailableAttributes: any = []

  // 失效过滤器
  private invalidFilters: number[] = []

  public async mounted() {
    if (this.filterGroup !== undefined) {
      this.filterGroupName = this.filterGroup.name
      await this.loadFilters()
    }
  }

  // 加载所有过滤器，并解析层级结构
  public async loadFilters() {
    // 获取子过滤
    const filters: Filter[] = await GraphAnalysis.queryGraphFilter({
      projectId: GraphAnalysis.projectId,
      graphId: GraphAnalysis.activeTabId,
      graphFilterPipelineId: this.filterGroup.id,
    })

    // 深度优先搜索，构建层级关系
    this.filters = []
    filters.forEach((filter) => {
      if (filter.parentId === null) {
        this.dfs(filters, filter, 0)
      }
    })

    // 如果没有过滤器，表示新建的，则自动添加一个
    if (this.filters.length === 0) {
      this.addCandidateFilter(null, null, 0)
    }
  }

  public dfs(filters: Filter[], filter: Filter, layer: number) {
    this.filters.push({ filter, layer })
    filters.forEach((f) => {
      if (f.parentId === filter.id) {
        this.dfs(filters, f, layer + 1)
      }
    })
  }

  // 是否可运行
  public get runable() {
    return true
  }

  // 如果只剩下最后一个过滤组，则这个过滤组不能删除
  public get deletable() {
    return GraphAnalysis.graphFilters.length > 1
  }

  // 当前激活的过滤器
  public get activeFilter() {
    return GraphAnalysis.activeFilter
  }

  // 当前正在运行的过滤流程
  public get runningFilterPipeline() {
    return GraphAnalysis.runningFilterPipelineId
  }

  // 计算竖线的长度
  public verticalLineHeight(layer: number, index: number) {
    for (let i = index - 1; i >= 0; i -= 1) {
      if (this.filters[i].layer === layer - 1) {
        return 32 * (index - i)
      }
    }
    return 0
  }

  // 加号根据不同过滤器，有不同提示
  public addIconHint(subType: number) {
    let hint = '添加子级'
    if (subType === 19) {
      hint = '添加并集'
    } else if (subType === 20) {
      hint = '添加交集'
    }
    return hint
  }

  // 如果选中的过滤器和当前过滤器一致，则hover高亮
  public itemStyle(id: number) {
    const selected = this.activeFilter !== null && id === this.activeFilter.id
    const style = {
      backgroundColor: selected ? 'rgba(103, 119, 252, 0.1)' : '',
    }
    return style
  }

  // 如果正在运行，则高亮
  public get headerStyle() {
    const selected = this.runningFilterPipeline === this.filterGroup.id
    const style = {
      backgroundColor: selected ? 'rgba(103, 119, 252, 0.1)' : '',
    }
    return style
  }

  @Watch('activeFilter')
  public async doneSetting() {
    // 如果设置修改了当前过滤组中的过滤器，则在本地修改
    if (
      this.activeFilter !== null &&
      this.activeFilter.graphFilterPipelineId === this.filterGroup.id
    ) {
      for (let i = 0; i < this.filters.length; i += 1) {
        if (this.filters[i].filter.id === this.activeFilter.id) {
          this.filters[i].filter.data = this.activeFilter.data
          this.$forceUpdate()
          break
        }
      }
    }
  }

  // 运行过滤
  @Emit('execute')
  public async runFilter(event: any) {
    event.stopPropagation()
    if (this.checkFilters()) {
      GraphAnalysis.setGraphAnalysisLoading(true)
      GraphAnalysis.setGraphAnalysisLoadingText('过滤器运行中')
      await this.loadFilters()

      const { tips, message } = await GraphAnalysis.executeFilterPipeline({
        projectId: GraphAnalysis.projectId,
        graphId: GraphAnalysis.activeTabId,
        id: this.filterGroup.id,
      })

      GraphAnalysis.setGraphAnalysisLoading(false)
      if (tips === null) {
        GraphAnalysis.setRunningFilterPipelineId(this.filterGroup.id)
        this.invalidFilters = []
        return this.filterGroup.id
      }
      this.$message.warning(message)
      const ids: string[] = tips.slice(1, -1).split(',')
      this.invalidFilters = ids.map((id) => Number.parseInt(id.trim(), 10))
      return null
    }
    return null
  }

  // 检查是否有没有填好的
  public checkFilters(): boolean {
    for (let i = 0; i < this.filters.length; i += 1) {
      const { filter } = this.filters[i]
      // 如果输入框值为空
      if (filter.subType === 7 || filter.subType === 14) {
        const { value } = filter.data.setParams[0]
        if (
          value === null ||
          value === undefined ||
          value.toString().trim() === ''
        ) {
          GraphAnalysis.setActiveFilter(filter)
          this.$message.warning('过滤器的值不能为空')
          return false
        }
      }
    }
    return true
  }

  // 过滤组正在改名
  public onEditting(event: any) {
    event.stopPropagation()
    this.isEditting = true
    this.$nextTick(() => {
      this.isEditting = true
    })
  }

  @Emit('groupRename')
  public async onRename() {
    this.isEditting = false

    // 重命名不能为空
    if (this.filterGroupName.trim() === '') {
      this.filterGroupName = this.filterGroup.name
      this.$message.warning('过滤组名不能全为空格')
      return null
    }
    // 判断有没有重名
    const duplicateNameGroupIndex = this.groups.findIndex((group: any) => {
      return (
        group.name === this.filterGroupName.trim() &&
        group.id !== this.filterGroup.id
      )
    })
    if (duplicateNameGroupIndex >= 0) {
      this.filterGroupName = this.filterGroup.name
      this.$message.warning('过滤组名不能重复')
      return null
    }
    this.filterGroup.name = this.filterGroupName
    // 传递给父组件
    return this.filterGroup
  }

  public onCollapseChange() {
    this.collapse = !this.collapse
  }

  // 选中行高亮，并且显示参数设置
  public onSelectRow(filter: Filter) {
    // 候选过滤器不予选中
    if (filter.id < 0) {
      return
    }
    const activeFilter = GraphAnalysis.activeFilter as Filter

    // 如果是已经选中了的，则取消选中
    if (activeFilter !== null && activeFilter.id === filter.id) {
      GraphAnalysis.setActiveFilter(null)
    } else {
      GraphAnalysis.setActiveFilter(filter)
    }
  }

  /**
   *  添加候选过滤器
   *  实现逻辑：
   *  1、找到当前候选过滤器最小的id值min，然后生成id为min-1的候选过滤器
   *  2、处理候选节点的父子关系：如果添加在一个候选过滤器前，那么需要将这个候选过滤器的parentid设置为新过滤器的id
   *  3、找到父节点的在所有过滤器列表中所在的下标
   *  4、如果父节点的过滤器类型是交集或并集，根据layer找到父节点中最后一个子节点，并添加到子节点后
   *  5、如果父节点的过滤器类型是其他，那么直接插入到父节点后，并更新其后面子孙节点的层次
   */
  public async addCandidateFilter(
    event: any | null,
    parentId: number | null,
    layer: number
  ) {
    if (event !== null) {
      event.stopPropagation()
    }

    // 找到候选过滤器的最小id
    let id = -1
    for (let i = 0; i < this.filters.length; i += 1) {
      if (this.filters[i].filter.id <= id) {
        id = this.filters[i].filter.id - 1
      }
    }

    // 处理候选节点的父子关系
    for (let i = 0; i < this.filters.length; i += 1) {
      if (this.filters[i].filter.id < 0) {
        if (this.filters[i].filter.parentId === parentId) {
          this.filters[i].filter.parentId = id
          break
        }
      }
    }

    // 候选过滤器
    const newFilter: any = {
      filter: {
        id,
        name: '请选择过滤条件',
        parentId,
      },
      layer,
    }
    const parentIndex: number = this.filters.findIndex(
      (f) => f.filter.id === parentId
    )

    // 如果是并集 和 交集，则加到后面
    if (
      this.filters[parentIndex]?.filter.subType === 19 ||
      this.filters[parentIndex]?.filter.subType === 20
    ) {
      let index = 0 // 插入位置
      // 找到父节点的位置
      for (let i = 0; i < this.filters.length; i += 1) {
        if (this.filters[i].filter.id === parentId) {
          index = i + 1
          // 如果之后的层次都是大于等于新插入的层次，则说明是兄弟节点或者兄弟节点的子节点
          // 新插入的位置解释层级小于新加入节点的层次的前一个节点
          for (; index < this.filters.length; index += 1) {
            if (
              this.filters[index].layer <
              this.filters[parentIndex]?.layer + 1
            ) {
              break
            }
          }
          break
        }
      }
      this.filters.splice(index, 0, newFilter)
    }
    // 如果是其他的，则把插入节点的子节点都加一层
    else {
      this.filters.splice(parentIndex + 1, 0, newFilter)
      // 处理层级
      for (let i = parentIndex + 2; i < this.filters.length; i += 1) {
        if (this.filters[i].layer >= layer) {
          const newLayer = this.filters[i].layer + 1
          this.filters[i].layer = newLayer
        } else {
          break
        }
      }
    }
  }

  // 后端加载可用属性
  public async loadAttributes(parentId: number | null) {
    // 查询可用属性
    const attributes = await GraphAnalysis.queryFilterAvailableAttributes({
      projectId: GraphAnalysis.projectId,
      graphId: GraphAnalysis.activeTabId,
      graphFilterPipelineId: this.filterGroup.id,
      parentId,
    })

    this.aviailableAttributes = []
    const keys: any = {
      7: '等于',
      8: '范围',
      9: '非空',
      10: '类别',
      11: '分类统计',
      12: '内部边',
      13: '外部边',
    }
    Object.keys(attributes).forEach((key) => {
      this.aviailableAttributes.push({
        key: keys[key],
        value: attributes[key].map((item: any) => {
          return { key: `${keys[key]}+${item}`, value: item }
        }),
      })
    })
  }

  // 更新过滤器
  public async updateFilter({ key }: any, layer: number, index: number) {
    let keyName = key.toString()
    let attribute = ''
    // 查找属性
    const attributeIndex: number = keyName.indexOf('+')
    if (attributeIndex >= 0) {
      attribute = keyName.slice(attributeIndex + 1, keyName.length)
      keyName = keyName.slice(0, attributeIndex)
    }

    const { type, subType } = filterMapType[keyName]
    // 原来的类型
    const oldType = this.filters[index].filter.subType

    const response = await GraphAnalysis.updateGraphFilter({
      ...this.filters[index].filter,
      type,
      subType,
      data: {
        attr: attribute,
      },
    })
    if (response.success) {
      const newFilter = response.result
      this.filters.splice(index, 1, { filter: newFilter, layer })
      GraphAnalysis.setActiveFilter(newFilter)

      // 如果更改的是并集或交集
      if (oldType === 19 || oldType === 20) {
        // 如果交集->并集，或者 并集->交集，则不变
        if (
          (oldType === 19 && subType === 20) ||
          (oldType === 20 && subType === 19)
        ) {
          console.log()
        } else {
          // 删除交集并集的子过滤器
          let i = index + 1
          for (; i < this.filters.length; i += 1) {
            if (this.filters[i].layer <= this.filters[index].layer) {
              break
            }
          }

          // 服务端删除
          for (let j = index + 1; j < i; j += 1) {
            if (this.filters[j].filter.id >= 0) {
              GraphAnalysis.deleteGraphFilter({ ...this.filters[j].filter })
            }
          }

          // 在本地删除
          this.filters.splice(index + 1, i - index - 1)
        }
      }
    }
  }

  /**
   *  添加过滤器
   *  实现逻辑：
   *  1、如果新添加的是根节点，或者父节点是一个候选过滤器，那么找到前面最近一个非候选节点的id作为新过滤器的父节点id
   *  2、判断所选中的过滤器是否有属性信息，如果包含+号，则+号后面的是选中的属性信息
   *  3、通过map映射找到选中过滤器类型名字对应的type和subtype
   *  4、添加过滤器成功后，用结果更新下标为index的过滤器，并且更新其子节点的parentId
   *  5、设置默认选中新添加节点，显示过滤设置
   */
  public async addFilter({ key }: any, parentId: number | null, index: number) {
    // 如果父节点也是一个候选过滤器
    if (parentId !== null && parentId < 0) {
      // 找到最近的父节点
      for (let i = index; i >= 0; i -= 1) {
        if (this.filters[i].filter.id >= 0) {
          parentId = this.filters[i].filter.id
          break
        }
      }

      // 如果前面没有选中的过滤器，则默认是null
      if (parentId !== null && parentId < 0) {
        parentId = null
      }
    }

    let keyName = key.toString()
    let attribute = ''

    // 查找属性
    const attributeIndex: number = keyName.indexOf('+')
    if (attributeIndex >= 0) {
      attribute = keyName.slice(attributeIndex + 1, keyName.length)
      keyName = keyName.slice(0, attributeIndex)
    }

    const { type, subType } = filterMapType[keyName]
    const response: any = await GraphAnalysis.addGraphFilter({
      projectId: GraphAnalysis.projectId,
      graphId: GraphAnalysis.activeTabId,
      graphFilterPipelineId: this.filterGroup.id,
      type,
      subType,
      parentId,
      data: {
        attr: attribute,
      },
    })
    if (response.success) {
      const oldId = this.filters[index].filter.id
      const newFilter = response.result
      this.filters.splice(index, 1, {
        filter: newFilter,
        layer: this.filters[index].layer,
      })
      // 将其子节点修改父节点id
      for (let i = 0; i < this.filters.length; i += 1) {
        if (this.filters[i].filter.parentId === oldId) {
          this.filters[i].filter.parentId = this.filters[index].filter.id
        }
      }
      GraphAnalysis.setActiveFilter(response.result)

      // 如果该节点是添加到根节点
      if (parentId === null) {
        // 判断其子节点是否为有父节点为null的，从1开始遍历，表示除了真正的根节点
        for (let i = 1; i < this.filters.length; i += 1) {
          if (this.filters[i].filter.parentId === null && i !== index) {
            this.filters[i].filter.parentId = newFilter.id
            GraphAnalysis.updateGraphFilter({
              ...this.filters[i].filter,
            })
            break
          }
        }
      }
    }
  }

  // 删除过滤器
  public async deleteFilter(event: any | null, index: number) {
    if (event !== null) {
      event.stopPropagation()
    }

    const filter = this.filters[index]
    // 把之后所有相关的层级再变回来
    for (let i = index; i < this.filters.length; i += 1) {
      if (this.filters[i].layer >= filter.layer) {
        const newLayer = this.filters[i].layer - 1
        this.filters[i].layer = newLayer
      }
    }

    if (filter.filter.id < 0) {
      this.filters.splice(index, 1)
      return
    }

    this.filters.splice(index, 1)

    const response = await GraphAnalysis.deleteGraphFilter({
      projectId: GraphAnalysis.projectId,
      graphId: GraphAnalysis.activeTabId,
      id: filter.filter.id,
    })
    if (response.success) {
      // 如果删除的选中过滤器，则设置选中过滤器为空
      if (filter.filter.id === this.activeFilter?.id) {
        GraphAnalysis.setActiveFilter(null)
      }
      if (this.filters.length === 0) {
        this.addCandidateFilter(null, null, 0)
      }
      // 判断删除的是不是根节点，如果是，且其子节点是候选节点，则修改候选节点的parentId
      if (this.filters.length > 0) {
        if (this.filters[0].filter.id < 0) {
          this.filters[0].filter.parentId = null
        }
      }
    }
  }

  @Emit('deleteGroup')
  public deleteFilterGroup() {
    // 如果删除的是选中节点的过滤组，则选中过滤节点置空
    if (this.activeFilter?.graphFilterPipelineId === this.filterGroup.id) {
      GraphAnalysis.setActiveFilter(null)
    }
    return this.filterGroup.id
  }
}
</script>

<style scoped lang="less">
.analysis-filter-group {
  width: 100%;
}

.group-header {
  align-items: center;
  cursor: pointer;
  display: flex;
  padding: 7px 15px;

  .group-name {
    color: #5d637e;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 1px;
    margin-left: 5px;
    padding: 0 5px;

    // 文本不可选中
    user-select: none;
  }

  .rename-input {
    margin: 0 10px;
  }

  .tab-name-edit-icon {
    cursor: pointer;
    display: none;
    font-size: 16px;
    margin-left: 2px;
  }

  .run-button {
    margin-left: auto;

    &:hover {
      background-color: #6973ff;
      color: #fff;
    }
  }

  .delete-button {
    cursor: pointer;
    font-size: 14px;
    margin-left: 10px;
  }

  &:hover {
    .tab-name-edit-icon {
      display: inline-block;
    }
  }
}

.filter-item {
  align-items: center;
  cursor: pointer;
  display: flex;
  padding: 7px 15px;
  position: relative;

  .circle {
    background: rgba(105, 115, 255, 0.6);
    border-radius: 50%;
    height: 6px;
    margin-left: 4px;
    width: 6px;
  }

  .short-horizontal-line {
    background-color: transparent;
    border-top: 1px solid rgba(162, 168, 253, 0.8);
    height: 1px;
    width: 16px;
  }

  .short-vertical-line {
    background-color: transparent;
    border-left: 1px solid rgba(162, 168, 253, 0.8);
    bottom: 20px;
    position: absolute;
    width: 1px;
  }

  .hint-msg {
    color: #222432;
    cursor: pointer;
    font-size: 14px;
    font-weight: 400;
    letter-spacing: 1px;
    margin-left: 10px;
    opacity: 0.3;
    // 文本不可选中
    user-select: none;
  }

  .selected-filter {
    color: #5d637e;
    cursor: pointer;
    font-size: 14px;
    font-weight: 400;
    letter-spacing: 1px;
    margin-left: 10px;
    // 文本不可选中
    user-select: none;
  }

  .dropdown {
    width: 110px;
  }

  .op-group {
    align-items: center;
    cursor: pointer;
    display: flex;
    flex-direction: row;
    font-size: 16px;
    justify-content: space-between;
    margin-left: auto;
    width: 50px;

    .del-noallowed {
      color: rgba(0, 0, 0, 0.2);
      cursor: not-allowed;
    }
  }

  &:hover {
    background-color: rgba(103, 119, 252, 0.1);

    .selected-filter {
      color: #6973ff;
    }
  }
}

.divider {
  border-top: 1px solid #e9e9e9;
  height: 1px;
  margin-top: 5px;
  width: 100%;
}
</style>
